package com.powerunion.datacollection.report.excelreport.base;

import java.util.ArrayList;
import java.util.List;

import com.powerunion.datacollection.report.excelreport.Logger;
import com.powerunion.datacollection.report.excelreport.base.element.Property;
import com.powerunion.datacollection.report.excelreport.util.AnalyseTempletTool;
import com.powerunion.datacollection.report.excelreport.util.HelpTools;

import jxl.Cell;
import jxl.CellFeatures;
import jxl.write.WritableCell;


/**
 * 报表自定义模板元素基类. 在报表模板文件中，每一个模板定义单元都被抽象成一个模板元素对象，
 * 当然，对于不同的模板元素对象其在生成报表过程当中的操作也不一样。
 * 因此在将一个模板元素描述的行为最终输出到报表上的实现是由模板元素的不同实现类自己来负责。
 * 
 * @author juny
 */
public abstract class BaseElement implements IElementWriter {
    public static final int ELEMENT_TYPE_BAND = 1;
    public static final int ELEMENT_TYPE_GROUP = 2;
    public static final int ELEMENT_TYPE_FIELD = 3;
    public static final int ELEMENT_TYPE_VARIABLE = 4;
    public static final int ELEMENT_TYPE_UNKNOWN = 4;
    private static Logger log = Logger.getLogger(BaseElement.class);
    /**
     * 设置包含该模板元素的容器对象
     */
    public BaseElement(ITempletContainer container) {
        parentContainer = container;
    }
    
    /**
     * 初始化模板元素变量，在模板文件分析完毕后系统会调用该函数来进行元素的
     * 一些初始化操作。
     */
    public void iniElement(){
        return;
    }
    
    /**
     * ××在某些情况下构造函数传入的container并不是其真正的父容器，遗留问题。
     * @param parentContainer
     */
    public void setParentContainer(ITempletContainer parentContainer){
        this.parentContainer = parentContainer;
    }

    /**
     * 取得当前报表模板元素名称 
     * @return 返回当前模板元素类型
     * @see ELEMENT_TYPE_BAND
     * @see ELEMENT_TYPE_GROUP
     * @see ELEMENT_TYPE_FIELD
     * @see ELEMENT_TYPE_VARIABLE
     * @see ELEMENT_TYPE_UNKNOWN
     */
    public int getType() {
        return ELEMENT_TYPE_UNKNOWN;
    }

    /**
     * 取得包含本模板元素的容器对象。
     * @return	返回容器对象
     */
    public ITempletContainer getParentContainer() {
        return parentContainer;
    }
    
    /**
     * 取得顶层容器
     * @return
     */
    public ITempletContainer getTopContainer(){
        if(null != topContainer){
            return topContainer;
        }
        
        topContainer = parentContainer;
        ITempletContainer old = null;
        while(topContainer != null){
            old = topContainer;
            topContainer = ((BaseElement)topContainer).getParentContainer();
        }
        topContainer = old;
        
        return topContainer;
    }
    private ITempletContainer topContainer = null;

    /**
     * 取得当前模板元素名称,每个模板元素都有其对应的名称，如band名称为其name属性定义的名称等，
     * 如果一个模板元素取了别名，该元素名称即为模板元素的别名。
     * @return
     */
    public String getName() {
        return name;
    }

    /*
     * @see excel.report.util.IElementWriter#setElementTempletValue(java.lang.String)
     */
    public void setElementTempletValue(String value) {
    	;
    }
    
    /**
     * 设置当前模板元素的名称
     * @param name	当前模板元素名称
     * @see	getName()
     */
    protected void setName(String name){
        this.name = name;
    }
    
    /**
     * 给字段添加一个写字段的监听器
     * @param listener	监听器对象
     */
    public final void addListener(IFieldValueListener listener){
        if(null == listener){
            return;
        }
        
        if(null == fieldValueListeners){
            fieldValueListeners = new ArrayList();
        }
        
        fieldValueListeners.add(listener);
    }
    
    
    
    public boolean equals(Object obj) {
        if(null == obj) return false;
        if(this == obj) return true;
        if(!(obj instanceof BaseElement)) return false;
        
        if(this.getName().equals(((BaseElement)obj).getName())){
            return true;
        }
        return false;
    }

    public boolean write(Parameter param) throws Exception {
        // TODO Auto-generated method stub
        return false;
    }

    /**
     * 取得所有监听器列表。
     * @return	返回本模板对象对应的监听器列表
     */
    protected final List getFieldValueListeners(){
        return this.fieldValueListeners;
    }
    
    public void setTempletCellRef(WritableCell cell){
    	templetCell = cell;    	
    	this.setProperties(cell);
    }
    
    public Cell getTempletCellRef(){
    	return this.templetCell;
    }
    
    /**
     * 设置一个基本模板变量的属性值
     * @param properties	属性值字符串,多个属性值用';'号隔开
     * @return true 属性值设置成功
     */
    public boolean setProperties(WritableCell cell){
    	
    	boolean bRet = false;
    	
    	if(null == cell) return false;
    	
    	CellFeatures cf = cell.getCellFeatures();
    	//如果当前元素支持属性设置,则读取当前单元模板变量,看是否设置了
        //模板元素的属性.        
    	if(null != cf){
    		String comment = cf.getComment();
    		String properties = null;
    		if(HelpTools.notEmpty(comment)){
                Property p = this.getPropertyInstance();
                if(null == p) return bRet;
                
    			StringBuffer sb = new StringBuffer(comment);
    			properties = AnalyseTempletTool.getProperties(sb);
    			if(HelpTools.notEmpty(properties)){
    				//如果当前元素支持属性设置,并且定义了相关属性,则读取当前单元模板变量,看是否设置了
    		    	//模板元素的属性.    				
    				bRet = p.setProperties(properties);
    				//如果有属性值,则需将属性值去掉
    				comment = sb.toString();
    				if(HelpTools.notEmpty(comment)){
    					cf.setComment(comment);
    				}else{
    					cf.removeComment();
    				}
                    
                    this.setProperty(p);
    			}
    		}
    	}
    	return bRet;
    }
    
    /**
     * 取得当前模板元素对象的属性保存对象.该对象用来保存所有属于该模板元素
     * 的属性.<br>
     * 子模板元素可以重载该函数来提供定制的属性对象..
     * @return
     */
    public Property getProperty(){
    	return property;
    }
    
    public void setProperty(Property property){
        this.property = property;
    }
    
    /**
     * 取得当前模板元素的属性类事例对象，系统默认提供Property。该类只能处理一些基本的<br>
     * 属性名称，属性值等一些普通的属性值。<br>
     * 如果程序需要处理一些特殊的属性值需要继承Property，来定制自己的属性类。
     * 继承类也可以重载该函数并返回一个null值来设置当前模板元数不支持属性定义。
     * @return
     */
    protected Property getPropertyInstance(){
        //return new Property();
        return null;
    }

    private Property property;
    private WritableCell templetCell;
    private ITempletContainer parentContainer = null;
    private List fieldValueListeners = null;
    private String name = null;
}